/*
 *Copyright (c) 2008, Scendix Software, Inc.
 * 
 */
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data.OleDb;
using System.Data; 
using Microsoft.MediaCenter.UI;
using System.Diagnostics;
using TapiRex;

using System.Threading;

namespace mceTapiRexv2
{
    /// <summary>
    /// This object contains the standard set of information displayed in the 
    /// details page UI.
    /// </summary>
    public class Phonecalls : ModelItem
    {
        /// <summary>
        /// List of Phonecall Objects 
        /// </summary>
        private List<Phonecall> lstPhonecalls = new List<Phonecall>();
        /// <summary>
        /// Gives the current page shown
        /// </summary>
        private int currPage = 0;
        /// <summary>
        /// Number of pages
        /// </summary>
        private int maxPage;
        private mceTapiRexv2.Utils.connectDB db = new mceTapiRexv2.Utils.connectDB();
        /// <summary>
        /// Keyword for search
        /// </summary>
        private String filter="";
        /// <summary>
        /// Show Answered calls
        /// </summary>
        private bool bAnswered = true;
        /// <summary>
        /// Show Unanswered calls
        /// </summary>
        private bool bUnanswered = true;
        /// <summary>
        /// Show Incoming calls
        /// </summary>
        private bool bIncoming = true;
        /// <summary>
        /// Show Outgoing calls
        /// </summary>
        private bool bOutgoing = true;
        /// <summary>
        /// Show calls of last x days
        /// </summary>
        private bool liveSearch = false;
        private bool filterChanged = true;
        private string condition = "";
        private String lookBack = "All";
        private string subtitle;
        __Application_evtIncomingCallEventHandler incomingHandler;
        __Application_evtOutgoingCallEventHandler outgoingHandler;
        public Phonecalls()
        {
            incomingHandler = new __Application_evtIncomingCallEventHandler(refresh);
            outgoingHandler = new __Application_evtOutgoingCallEventHandler(refresh);
            mceTapiRexv2.Application.Current.TapiRexApplication.evtIncomingCall += incomingHandler;
            mceTapiRexv2.Application.Current.TapiRexApplication.evtOutgoingCall += outgoingHandler;

        }
        ~Phonecalls()
        {
            mceTapiRexv2.Application.Current.TapiRexApplication.evtIncomingCall -= incomingHandler;
            mceTapiRexv2.Application.Current.TapiRexApplication.evtOutgoingCall -= outgoingHandler;

        }

        public void refresh(int id)
        {
            Thread.Sleep(500);
            Debug.WriteLine("refreshing call list!");
            refreshCallList();
        }
        public void refreshCallList()
        {
            Debug.WriteLine("refreshing Call List");
            loadCalls();
        }
        public List<Phonecall> CallList
        {
            get
            {
                if (lstPhonecalls.Count == 0 && filterChanged)
                {
                    Debug.WriteLine("get Call List");
                    loadCalls();
                }

                return lstPhonecalls;
            }
            set
            {
                    
                    lstPhonecalls = value;
            }
        }
        private String buildCondition(int offset)
        {
            List<String> cond = new List<string>();
            string condition = "";
            if (this.filter != "" && this.filter != null)
            {
                List<string> criterias = new List<string>();
                criterias.Add("CallerID");
                criterias.Add("CalledID");
                criterias.Add("CallerName");
                criterias.Add("CalledName");
                string keywordCond = "";
                string neg = "";
                string[] words = this.filter.Split(' ');
                int i = 0;
                foreach (string word in words)
                {
                    string searchExpression = word.Trim();
                    if (searchExpression == "" || searchExpression == " " || searchExpression=="-") break;
                    string condOp;
                    if (searchExpression.Substring(0, 1) == "-")
                    {
                        neg = "NOT";
                        condOp = " AND ";
                        searchExpression = searchExpression.Substring(1);
                    }
                    else condOp = " OR ";
                    if (i++ > 0) keywordCond += " AND ";
                    int j = 0;
                     foreach (string crit in criterias)
                    {
                        if (j++ == 0) keywordCond += "(";
                        else keywordCond += condOp;
                        keywordCond += "((" + crit + ") " + neg + " LIKE '%" + searchExpression + "%')";
                    }
                    keywordCond += ")";
                    cond.Add(keywordCond);
                }
            }
            if (bUnanswered == false && bAnswered==true)
            {
                cond.Add(" Answered ");
            }
            if (bUnanswered == true && bAnswered == false)
            {
                cond.Add(" NOT(Answered) ");
            }
            if (bIncoming == true && bOutgoing == false)
            {
                cond.Add(" Incoming ");
            }
            if (bIncoming == false && bOutgoing == true)
            {
                cond.Add(" NOT(Incoming) ");
            }
            if (lookBack != "All")
            {
                cond.Add(" ( CallDate > (NOW()-" + lookBack + ")) ");
            }
            string tempCondition = "";
            if (cond.Count > 0)
            {
                int j = 0;
                
                foreach(String sCondition in  cond)
                {
                    if (j++ > 0) tempCondition += " AND "; 
                    tempCondition += sCondition;
                }
            }
            if (offset > 0)
            {
                if (tempCondition == "")
                    condition = " (CallID NOT IN (SELECT TOP " + offset.ToString() + " CallID FROM Calls ORDER BY CallDate DESC)) ";
                else
                {
                    condition = " (CallID NOT IN (SELECT TOP " + offset.ToString() + " CallID FROM Calls " +
                        "WHERE " + tempCondition + " ORDER BY CallDate DESC)) AND " + tempCondition;
                }
            }
            else condition = tempCondition;
            if (condition != "")
                condition = "WHERE " + condition;
            return condition;
        }
        private void loadCalls()
        {
            List<Phonecall> lstCalls = new List<Phonecall>();
            filterChanged = false;
            string top = (mceTapiRexv2.Application.Current.itemsPP != "all") ? " TOP "+mceTapiRexv2.Application.Current.itemsPP : "";
            //If "all" is selected, int.parse crashes. Added try/catch to check it.
            int itemsPPtemp,offset;
            try
            {
                itemsPPtemp = int.Parse(mceTapiRexv2.Application.Current.itemsPP);
                offset = itemsPPtemp * this.currPage;
            }

            catch
            {
                offset = 0;
                itemsPPtemp = 1;
            }
            string cond;
            if (filterActive() == false && condition != "")
                cond = condition;
            else cond = buildCondition(offset);
            
            string strSQL = "SELECT "+top+" CallDate,CallEnd,CallerID,CallerName,CalledName,Incoming,Answered, "+
                "New,CalledID,CallerGUID,CalledGUID, (SELECT COUNT(*) FROM Calls " + cond + ") FROM "+
                "Calls " + cond + "  ORDER BY CallDate DESC";
            
            DataSet dr = db.SelectQuery(strSQL);
            DataTable dt = dr.Tables[0];
            bool maxPageUpdate=false;
            if (dt != null && dt.Rows.Count > 0)
            {
                foreach (DataRow row in dt.Rows)
                {
                    Phonecall pc = new Phonecall(row);
                    if (!maxPageUpdate)
                    {
                        int nCalls = Int32.Parse(row[11].ToString()) + itemsPPtemp;
                        double temp = (double)nCalls / itemsPPtemp;
                        this.maxPage = (int)Math.Ceiling(temp) - 1;
                        FirePropertyChanged("hasNextPage");
                        FirePropertyChanged("hasPrevPage");
                        maxPageUpdate = true;
                    }
                    lstCalls.Add(pc);
                }
            }
            else
            {
                if (dt.Rows.Count == 0)
                {
                    this.maxPage = 0;
                    this.currPage = 0;
                    FirePropertyChanged("hasNextPage");
                    FirePropertyChanged("hasPrevPage");

                }
            }
            lstPhonecalls = lstCalls;
            FirePropertyChanged("CallList");
        }
        public bool hasPrevPage()
        {
            return (this.currPage > 0);
        }
        public bool hasNextPage()
        {
            return (this.currPage < this.maxPage-1);
        }
        public void nextPage()
        {
            if (this.currPage < this.maxPage)
            {
                this.currPage++;
                FirePropertyChanged("hasNextPage");
                FirePropertyChanged("hasPrevPage");
                lstPhonecalls = new List<Phonecall>();
                loadCalls();
            }
        }
        public void prevPage()
        {
            if (this.currPage > 0)
            {
                this.currPage--;
                FirePropertyChanged("hasNextPage");
                FirePropertyChanged("hasPrevPage");
                lstPhonecalls = new List<Phonecall>();
                 loadCalls();
            }
        }
        public string Subtitle
        {
            get
            {
                if (condition.Trim() != "")
                {
                    if (bShowIncoming() && filter.Trim()=="")
                        return mceTapiRexv2.Application.Current.getResString("1628",subtitle);
                    else if (bShowMissedCalls() && filter.Trim() == "")
                        return mceTapiRexv2.Application.Current.getResString("1630",subtitle);
                    else if (bShowOutgoing() && filter.Trim() == "")
                        return mceTapiRexv2.Application.Current.getResString("1629",subtitle);
                    else if( filter.Trim()=="")
                        return mceTapiRexv2.Application.Current.getResString("1632",subtitle);
                    return mceTapiRexv2.Application.Current.getResString("1631", subtitle);
                }
                if (bShowIncoming())
                    return mceTapiRexv2.Application.Current.getResString("455");
                 if (bShowMissedCalls())
                    return mceTapiRexv2.Application.Current.getResString("864");
                 if (bShowOutgoing())
                    return mceTapiRexv2.Application.Current.getResString("1095");
                 if (!filterActive()) 
                     return mceTapiRexv2.Application.Current.getResString("602");

                return mceTapiRexv2.Application.Current.getResString("1626");
            }
            set
            {
                subtitle = value;
                FirePropertyChanged("Subtitle");
            }
        }
                 
        public bool filterActive()
        {
            return (!bAnswered || !bUnanswered || !bIncoming || !bOutgoing || filter != "");
        }
        public bool bShowIncoming()
        {
            return (bIncoming && !bOutgoing && bAnswered);
        }
        public bool bShowOutgoing()
        {
            return (!bIncoming && bOutgoing && bAnswered);
        }
        public bool bShowMissedCalls()
        {
            return (bIncoming && !bOutgoing && !bAnswered);
        }
        public Choice TimeSelect
        {
            get
            {
                Choice timeChoice = new Choice();
                List<String> options = new List<string>();
                String opt = "All";
                options.Add(opt);
                for (int i = 1; i <= 4; i++)
                {
                    opt = (i).ToString();
                    options.Add(opt);
                }
                for (int k = 1; k <= 5; k++)
                {
                    opt = (k * 5).ToString();
                    options.Add(opt);
                }
                timeChoice.Options = options;
                timeChoice.Chosen = lookBack;
                timeChoice.Default = lookBack;
                return timeChoice;
            }
        }

        /// <summary>
        /// resets the filter so all calls are shown
        /// </summary>
        public void resetFilter()
        {
            if (filterActive())
            {
                showAnswered = true;
                showUnanswered = true;
                showIncoming = true;
                Keyword = "";
                showOutgoing = true;
                loadCalls();
                fireSearchOptionChange();

            }
        }
        private void fireSearchOptionChange()
        {
            FirePropertyChanged("filterActive");
            FirePropertyChanged("bShowOutgoing");
            FirePropertyChanged("bShowMissedCalls");
            FirePropertyChanged("bShowIncoming");
            FirePropertyChanged("hasNextPage");
            FirePropertyChanged("hasPrevPage");
            FirePropertyChanged("Subtitle");
        }
        /// <summary>
        /// filters out all outgoing calls
        /// </summary>
        public void showIncomingCalls()
        {
            if (!bShowIncoming())
            {
                showIncoming = true;
                showOutgoing = false;
                showAnswered = true;
                showUnanswered = true;
                loadCalls();
                fireSearchOptionChange();
            }
        }
        /// <summary>
        /// filters out incoming calls
        /// </summary>
        public void showOutgoingCalls()
        {
            if (!bShowOutgoing())
            {
                showIncoming = false;
                showOutgoing = true;
                showAnswered = true;
                showUnanswered = true;
                loadCalls();
                fireSearchOptionChange();
           
            }
        }
        /// <summary>
        /// filters out all answered calls
        /// </summary>
        public void showMissedCalls()
        {
            if (!bShowMissedCalls())
            {
                showIncoming = true;
                showOutgoing = false;
                showAnswered = false;
                showUnanswered = true;
                loadCalls();
                fireSearchOptionChange();
           
            }
        }
        public String Keyword
        {
            get { return filter; }
            set{
                if (this.filter != value)
                {
                    this.filter = value;
                    Debug.WriteLine("Keyword changed to " + value);
                    filterChanged = true;
                    if (liveSearch)
                        loadCalls();
                    FirePropertyChanged("Keyword");
                    FirePropertyChanged("Subtitle");
                }
            }
        }
        public bool showAnswered
        {
            get { return bAnswered; }
            set
            {
                if (this.bAnswered != value)
                {
                    this.bAnswered = value;
                    Debug.WriteLine("showAnswered changed to " + value.ToString());
                    filterChanged = true;
                    if (liveSearch)
                        loadCalls();
                    FirePropertyChanged("showAnswered");
                }
           }
        }
        public bool showUnanswered
        {
            get { return bUnanswered; }
            set
            {
                if (this.bUnanswered != value)
                {
                    this.bUnanswered = value;
                    Debug.WriteLine("showUnanswered changed to " + value.ToString());
                    filterChanged = true;
                    if (liveSearch)
                        loadCalls();
                    FirePropertyChanged("showUnanswered");
                }

            }
        }
        public bool showIncoming
        {
            get { return bIncoming; }
            set
            {
                if (bIncoming != value)
                {
                    this.bIncoming = value;
                    Debug.WriteLine("showIncoming changed to " + value.ToString());
                    filterChanged = true;
                    if (liveSearch)
                        loadCalls();
                    FirePropertyChanged("showIncoming");
                }
            }
        }

        public bool showOutgoing
        {
            get { return bOutgoing; }
            set
            {
                if (this.bOutgoing != value)
                {
                    this.bOutgoing = value;
                    Debug.WriteLine("showOutgoing changed to " + value.ToString());
                    filterChanged = true;
                    if (liveSearch)
                        loadCalls();
                    FirePropertyChanged("showOutgoing");
                }
               }
        }
        public bool LiveSearch
        {
            set { liveSearch = value; }
            get { return liveSearch; }
        }
        public String LookBack
        {
            set
            {
                lookBack = value;
                FirePropertyChanged("LookBack");
            }
            get
            {
                return lookBack;
            }
        }
        public string Condition
        {
            set
            {
                condition = value;
                fireSearchOptionChange();
            }
            get
            {
                return condition;
            }
        }
    }
    
}
